// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of RegistryLookup
//
// RegistryLookup is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// RegistryLookup is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with RegistryLookup. If not, see <http://www.gnu.org/licenses/>.
//	
//
//	Purpose: Error information functions for RegistryLookup.
//   $Id$

#include "stdafx.h"
#include "ReturnCodes.h"
#include <atlstr.h>

// Set up the IErrorInfo interface.
HRESULT SetupErrorInfo(HRESULT errcode, ...)
{
	HRESULT hr = S_OK;

	try {
		// Check errcode is valid.
		if(IS_RL_CODE(errcode) && FAILED(errcode)) {

			// Create an error info object
			CComPtr<ICreateErrorInfo> pCreateErrorInfo;
			hr = ::CreateErrorInfo(&pCreateErrorInfo);

			if(SUCCEEDED(hr)) {
				// Set the error message.
				CStringW sError;
				va_list args;
				va_start(args, errcode);
				switch(errcode) {
					case RL_E_NOMIMETYPE:
						sError.FormatV(L"The file extension '%s' has no registered mimetype associated with it.", args);
						break;
					case RL_E_BADEXT:
						sError.FormatV(L"The file extension '%s' is not registered.", args);
						break;
					case RL_E_BADARG:
						sError.FormatV(L"An invalid argument was passed to '%s'.", args);
						break;
					case RL_E_BADROOTKEY:
						sError.FormatV(L"An invalid root key was specified in a request to '%s'.", args);
						break;
					case RL_E_BADVALUE:
						sError.FormatV(L"Unable to %s the value '%s' in registry key '%s\\%s'.", args);
						break;
					case RL_E_UNAUTH:
						sError.FormatV(L"The user did not authorise a %s of the value '%s' in registry key '%s\\%s'. Operation aborted.", args);
						break;
					case RL_E_BADTYPEREAD:
						sError.FormatV(L"The %s registry type can not be read into a string variable.", args);
						break;
					case RL_E_NOMEM:
						sError.FormatV(L"A memory allocation failed in '%s'. The system may be running low on virtual memory.", args);
						break;
					case RL_E_OPENKEY:
						sError.FormatV(L"Unable to open registry key '%s\\%s'.", args);
						break;
					default:
						sError = L"An unexpected error has occurred inside the RegistryLookup component.";
				}
				
				// Setup the error info object.
				hr = pCreateErrorInfo->SetSource(CComBSTR(L"RegistryLookup"));
				if(SUCCEEDED(hr)) {
					CComBSTR sErrorArg;
					sErrorArg.Attach(sError.AllocSysString());
					hr = pCreateErrorInfo->SetDescription(sErrorArg);
					if(SUCCEEDED(hr)) {
						CComQIPtr<IErrorInfo> pErrorInfo = pCreateErrorInfo;
						if(pErrorInfo)
							hr = ::SetErrorInfo(0, pErrorInfo);
					}
				}
			}
		} else
			hr = E_INVALIDARG;
	}

	catch(...) {
		hr = E_FAIL;
	}

	return hr;
}

// Report an error, using the IErrorInfo interface if possible.
HRESULT ReportErrorInfo(HRESULT errcode, HWND hWndOwner)
{
	CComPtr<IErrorInfo> pErrorInfo;
	CString sErrorInfo;

	// Try to get an IErrorInfo pointer.
	HRESULT hr = ::GetErrorInfo(0, &pErrorInfo);
	if(hr == S_OK) {
		// Get the description from the IErrorInfo pointer.
		CComBSTR sErrorDescription;
		pErrorInfo->GetDescription(&sErrorDescription);

		// Get the source from the IErrorInfo pointer.
		CComBSTR sErrorSource;
		pErrorInfo->GetSource(&sErrorSource);

		// Format the error string.
		sErrorInfo.Format("The following exception has been caught inside the RegistryLookup component:\n\n%S\n\nThe error code associated with this exception is 0x%08x (%d).\n\nThe source component of this exception has been identified as '%S'.", sErrorDescription, errcode, errcode, sErrorSource);
	} else
		// Format a generic error string.
		sErrorInfo.Format("An unidentified exception has been caught inside the RegistryLookup component.\n\nThe error code associated with this exception is 0x%08x (%d).\n\nNo further error information is available.", errcode, errcode);

	// Report the error to the user.
	::MessageBox(hWndOwner, sErrorInfo.GetString(), "RegistryLookup - Error", MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND);

	return hr;
}
